/*
 * Time : 2022/12/3 17:35
 * Auth : weixinlong
 * Email : weixinlong@buaa.edu.cn
 * File : models.go
 */

package model

import (
	"encoding/json"
	"time"
)

const (
	// 标注结果在正常标注中
	LABEL_WORKING = "working"

	// 标注结果已经提交以供审查
	LABEL_SUBMIT = "submit"

	// 标注结果被打回
	LABEL_REJECT = "reject"

	// 标注结果已经确认为最后结果
	LABEL_CONFIRM = "confirm"
)

func IsValidLabelStatus(status string) bool {
	if status == LABEL_WORKING {
		return true
	}

	if status == LABEL_SUBMIT {
		return true
	}

	if status == LABEL_REJECT {
		return true
	}

	if status == LABEL_CONFIRM {
		return true
	}
	return false
}

type Label struct {
	ID        uint      `gorm:"primaryKey;not null" json:"id"`
	CreatedAt time.Time `json:"created_at,omitempty"`
	UpdatedAt time.Time `json:"updated_at,omitempty"`

	// 标注结果的具体数据
	Data string `json:"data"`

	// 标注结果相关的注释
	Comment string `json:"comment"`

	// 标注结果的审核状态
	Status string `gorm:"not null;default:working" json:"status"`

	// 标注结果的用户名
	AuthorID uint `gorm:"not null" json:"author_id"`

	// 标注对应的media
	MediaID uint `gorm:"not null" json:"media_id"`

	// 标注对应的mission
	MissionID uint `json:"mission_id"`
}

func (r Label) PrimaryKey() uint {
	return r.ID
}

type Media struct {
	ID        uint      `gorm:"primaryKey;not null" json:"id"`
	CreatedAt time.Time `json:"created_at,omitempty"`
	UpdatedAt time.Time `json:"updated_at,omitempty"`

	// DICOM视频的uid
	InstanceUid string `gorm:"not null" json:"instance_uid"`

	// 视频文件的DICOM 序列号, series number
	SeriesNumber uint `gorm:"not null" json:"series_number"`

	// 视频文件的DICOM 序列号, instance number
	InstanceNumber uint `gorm:"not null" json:"instance_number"`

	// DICOM视频文件的sha1 hash, 使用小写16进制格式
	SHA1 string `gorm:"not null" json:"sha1"`

	// 视频DICOM文件相对于DICOMDIR文件所在目录的位置
	Path string `gorm:"not null" json:"path"`

	// 视频所属的切面
	View string `gorm:"not null" json:"view"`

	// 视频的所有标签
	Labels []Label `json:"labels"`

	// 视频相关的注释
	Comment string `json:"comment"`

	// media所属的selection的ID
	SelectionID uint `gorm:"not null" json:"selection_id"`

	// 视频所属的样本的ID
	SampleID string `gorm:"not null" json:"sample_id"`
}

func (r Media) PrimaryKey() uint {
	return r.ID
}

type User struct {
	ID        uint      `gorm:"primaryKey;not null" json:"id"`
	CreatedAt time.Time `json:"created_at,omitempty"`
	UpdatedAt time.Time `json:"updated_at,omitempty"`

	// 用户名
	Username string `gorm:"unique;not null" json:"username"`

	// bcrypt加密的密码, json编码时忽略这一字段, 防止密码流出
	Password string `json:"-"`

	// 用户是否是管理员, 只有管理员可以进行用户管理
	IsAdmin bool `gorm:"not null" json:"is_admin"`

	// 用户是否已经被禁用
	Disable bool `gorm:"not null" json:"disable"`
}

func (r User) PrimaryKey() uint {
	return r.ID
}

// 样本, 每个dicom study都是一个样本
type Sample struct {
	// 样本的ID, 使用study的SOP instance uid
	ID        string    `gorm:"primaryKey;not null" json:"id"`
	CreatedAt time.Time `json:"created_at,omitempty"`
	UpdatedAt time.Time `json:"updated_at,omitempty"`

	// dicomdir 所在目录的路径
	Path string `gorm:"not null" json:"path"`

	// 样本的所有筛选结果
	Selections []Selection `gorm:"constraint:OnUpdate:CASCADE,OnDelete:CASCADE" json:"selections"`

	// 包含study的DICOMDIR文件的sha1 hash, 使用小写16进制格式
	DICOMDIRHash string `gorm:"not null" json:"dicomdir_hash"`
}

func (r Sample) PrimaryKey() string {
	return r.ID
}

const (
	// 样本筛选正常筛选中
	SELECTION_WORKING = "working"

	// 样本筛选已经提交以供审查
	SELECTION_SUBMIT = "submit"

	// 样本筛选被打回
	SELECTION_REJECT = "reject"

	// 样本筛选已经确认为最后结果
	SELECTION_CONFIRM = "confirm"
)

// 样本筛选表, 每个用户对于样本的筛选
type Selection struct {
	// 筛选的ID
	ID        uint      `gorm:"primaryKey;not null" json:"id"`
	CreatedAt time.Time `json:"created_at,omitempty"`
	UpdatedAt time.Time `json:"updated_at,omitempty"`

	// 做出筛选的用户
	AuthorID uint `gorm:"not null" json:"author_id"`

	// 进行筛选的样本
	SampleID string `gorm:"not null" json:"sample_id"`

	// 样本的标注
	Label string `json:"label"`

	// 最终确认样本的管理员的用户ID
	AdminID *uint `json:"admin_id,omitempty"`

	// 筛选样本的状态
	Status string `gorm:"not null;default:working" json:"status"`

	// 筛选出的视频
	Medias []Media `gorm:"constraint:OnUpdate:CASCADE,OnDelete:CASCADE" json:"medias"`

	// 注释
	Comment string `json:"comment"`
}

func (r Selection) PrimaryKey() uint {
	return r.ID
}

func IsValidSelectionStatus(status string) bool {
	if status == SELECTION_WORKING {
		return true
	}

	if status == SELECTION_SUBMIT {
		return true
	}

	if status == SELECTION_REJECT {
		return true
	}

	if status == SELECTION_CONFIRM {
		return true
	}
	return false
}

// 任务表,把某个样本或筛选分配给某个用户
type Job struct {
	// 任务ID
	ID        uint      `gorm:"primaryKey;not null" json:"id"`
	CreatedAt time.Time `json:"created_at,omitempty"`
	UpdatedAt time.Time `json:"updated_at,omitempty"`

	// 任务所属的用户id
	AuthorID uint `gorm:"not null" json:"author_id"`

	// 任务对应样本
	SampleID string `gorm:"not null" json:"sample_id"`

	// 任务对应筛选
	SelectionID uint `gorm:"not null" json:"selection_id"`
}

// Mission表,不同轮次任务
type Mission struct {
	// ID
	ID        uint      `gorm:"primaryKey;not null" json:"id"`
	CreatedAt time.Time `json:"created_at,omitempty"`
	UpdatedAt time.Time `json:"updated_at,omitempty"`

	// 任务名称
	Name string `gorm:"unique;not null" json:"name"`

	// 需要标注的内容
	Label string `gorm:"not null" json:"label"`

	// 任务所属的用户id
	AuthorID uint `gorm:"not null" json:"author_id"`

	// 注释
	Comment string `json:"comment"`
}

// Collection表, 表示信息收集表
type Collection struct {
	// 主键
	ID       uint      `gorm:"primaryKey;not null" json:"id"`
	CreateAt time.Time `json:"create_at,omitempty"`
	UpdateAt time.Time `json:"update_at,omitempty"`

	// 是否启用
	Enable bool `json:"enable"`

	// 收集表名称
	Name string `gorm:"unique;not null" json:"name"`

	// 创建者名称
	AuthorID uint `gorm:"not null" json:"author_id"`

	// 信息收集表的结构
	Schema json.RawMessage `gorm:"not null" json:"schema"`

	// 说明
	Comment string `json:"comment"`
}

// Report表, 结构化报告表
type Report struct {
	// 主键
	ID       uint      `gorm:"primaryKey;not null" json:"id"`
	CreateAt time.Time `json:"create_at,omitempty"`
	UpdateAt time.Time `json:"update_at,omitempty"`

	// 信息收集表的名称
	CollectionID uint `gorm:"not null" json:"collection_id"`

	// 创建者名称
	AuthorID uint `gorm:"not null" json:"author_id"`

	// 患者唯一编码
	PatientID string `gorm:"not null"`

	// 结构化报告表的内容
	Content json.RawMessage `gorm:"not null" json:"content"`
}
